﻿using System;
using NUnit.Framework;
using SmartPeople.Framework.SecuritySpace;
using SmartPeople.Framework.SecuritySpace.Tests;

namespace SmartPeople.Framework.SecuritySpace.Provider.Tests
{
    [TestFixture]
    public class SecurityPermissionTests
    {
        private static readonly Guid role1ID = new Guid("{00000000-0000-0000-1001-000000000000}");
        private static readonly Guid role2ID = new Guid("{00000000-0000-0000-1002-000000000000}");
        private static readonly Guid document1ID = new Guid("{00000000-0000-0000-2001-000000000000}");
        private static readonly Guid action1ID = new Guid("{00000000-0000-0000-3001-000000000000}");
        private static readonly Guid action2ID = new Guid("{00000000-0000-0000-3002-000000000000}");

        public void Initialize(ISecuritySpace securitySpace)
        {
            //there are folders
            //ISecuritySecuredType securedFolder = securitySpace.SecuredTypes.CreateType("folder");
            ////with actions available
            //securedFolder.Actions.CreateAction(TestActions.List);
            //securedFolder.Actions.CreateAction(TestActions.Read);
            //securedFolder.Actions.CreateAction(TestActions.Create);
            //securedFolder.Actions.CreateAction(TestActions.Modify);
            //securedFolder.Actions.CreateAction(TestActions.Delete);

            //securitySpace.SecuredTypes.UpdateSecuredType(securedFolder);


            //there are unknown files
            //ISecuritySecuredType securedFile = securitySpace.SecuredTypes.CreateType("unknownFileType");
            ////with actions available
            //securedFile.Actions.CreateAction(TestActions.Read);
            //securedFile.Actions.CreateAction(TestActions.Create);
            //securedFile.Actions.CreateAction(TestActions.Modify);
            //securedFile.Actions.CreateAction(TestActions.Delete);

            ////with states
            //securedFile.States.CreateState(TestStates.New);
            //securedFile.States.CreateState(TestStates.Normal);
            //securedFile.States.CreateState(TestStates.Protected);
            //securitySpace.SecuredTypes.UpdateSecuredType(securedFile);

            //there are properties
            ISecuritySecuredType baseSecuredProperty = securitySpace.SecuredTypes.CreateType("BaseProperty");
            //actions on them available
            baseSecuredProperty.Actions.CreateAction(TestActions.Get);
            baseSecuredProperty.Actions.CreateAction(TestActions.Set);
            securitySpace.SecuredTypes.UpdateSecuredType(baseSecuredProperty);

            ISecuritySecuredType securedFolder = securitySpace.SecuredTypes.GetSecuredType("folder");
            securitySpace.SecuredDocuments.SetDefaultPathType(securedFolder);
            ISecuritySecuredType securedFile = securitySpace.SecuredTypes.GetSecuredType(BuiltInSecuredTypes.Folder);
            securitySpace.SecuredDocuments.SetDefaultDocumentType(securedFile);

            //create three roles
            securitySpace.Roles.CreateRole(TestRoles.Administrators);
            securitySpace.Roles.CreateRole(TestRoles.Operators);
            securitySpace.Roles.CreateRole(TestRoles.Users);


            securitySpace.Users.CreateUser(TestUsers.System, TestUsers.User1Password, "system@acme.com",
                                           "What is you fathers middle name?", "Douglas", true, "System User Comment");
            securitySpace.Users.CreateUser(TestUsers.Administrator, "admin", "administrator@acme.com",
                                           "What is you fathers middle name?", "Douglas", true, "System User Comment");
            securitySpace.Users.CreateUser(TestUsers.Guest, "guest", "guest@acme.com",
                                           "What is you fathers middle name?", "Douglas", true, "System User Comment");
            securitySpace.Users.CreateUser(TestUsers.User1, "user1", "user1@acme.com",
                                           "What is you fathers middle name?", "Douglas", true, "System User Comment");
        }

        [Test, Description("Misc security space tests")]
        public void SecuritySpaceObjectCreationTests()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace("TA");
            securitySpace.Clear();
            Initialize(securitySpace);
            //check how many roles (should be three)
            Assert.AreEqual(3, securitySpace.Roles.GetAllRoles().Length);
            //check how many types (should be three)
            Assert.AreEqual(3, securitySpace.SecuredTypes.GetAllSecuredTypes().Length);
            //check if 5 actions for securedFolder
            Assert.AreEqual(5, securitySpace.SecuredTypes.GetSecuredType("folder").Actions.Count);
            //check if 4 actions for securedFile
            Assert.AreEqual(4, securitySpace.SecuredTypes.GetSecuredType("unknownFileType").Actions.Count);
            //check if 2 actions for BaseProperty
            Assert.AreEqual(2, securitySpace.SecuredTypes.GetSecuredType("BaseProperty").Actions.Count);
            //check if 3 roles where created
            Assert.AreEqual(3, securitySpace.Roles.GetAllRoles().Length);
            //check if 4 users have been created
            Assert.AreEqual(4, securitySpace.Users.GetAllUsers().Length);
            //check if 3 states exists for unknownFileType

            //the build in filetype does not have states
            Assert.AreEqual(0, securitySpace.SecuredTypes.GetSecuredType("unknownFileType").States.Count);
            //check if no state exists for folder
            Assert.AreEqual(0, securitySpace.SecuredTypes.GetSecuredType("folder").States.Count);
            //check if no state exists for baseproperty
            Assert.AreEqual(0, securitySpace.SecuredTypes.GetSecuredType("BaseProperty").States.Count);
            //check if any permission exist 
            Assert.AreEqual(0, securitySpace.SecurityPermissions.Count);
            ISecurityPermissions securityPermissions = TestsHelper.GetSecurityPermissions();
            Guid roleid = securitySpace.Roles.GetRole(TestRoles.Administrators).GID;
            Guid docid = securitySpace.SecuredTypes.GetSecuredType("folder").GID;
            Assert.IsNotNull(roleid);
            securityPermissions.CreatePermission(roleid, docid, AccessType.Allow);
            Assert.AreEqual(1, securitySpace.SecurityPermissions.Count);
            //securitySpace.SecuredDocuments.CreateDocument()

            securitySpace.Clear();
        }

        [Test, Description("Deny permission on action")]
        public void DenyPermissionOnRole()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            ISecurityPermissions securityPermissions = TestsHelper.GetSecurityPermissions();
            bool authorized = true;
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsFalse(authorized);
            Assert.AreEqual(0, securityPermissions.GetPermissions(role1ID, document1ID).Length);
            //grant full control.
            securityPermissions.CreatePermission(role1ID, document1ID, AccessType.Allow);
            //check for unkown state and unkown action.
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsTrue(authorized, "role1 should have full control for document1");
            Assert.AreEqual(1, securityPermissions.GetPermissions(role1ID, document1ID).Length);
            //now deny all Permissions
            securityPermissions.DenyPermission(role1ID, document1ID);
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsFalse(authorized);
            //other roles should still not authorized  
            authorized = securityPermissions.IsGranted(role2ID, document1ID);
            Assert.IsFalse(authorized);
            //Assert.AreEqual(securedPath.FullName, securedPath1.FullName);

            securityPermissions.DenyPermission(role1ID, document1ID);

            authorized = securityPermissions.IsGranted(role2ID, document1ID);
            Assert.IsFalse(authorized);

            securitySpace.Clear();
        }


        [Test, Description("Deny permission on document")]
        public void DenyPermissionOnRoleWithRoleDocAction()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            ISecurityPermissions securityPermissions = TestsHelper.GetSecurityPermissions();
            bool authorized = true;
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsFalse(authorized);
            Assert.AreEqual(0, securityPermissions.GetPermissions(role1ID, document1ID).Length);


            securityPermissions.CreatePermission(role1ID, document1ID, action1ID, AccessType.Allow);
            securityPermissions.CreatePermission(role1ID, document1ID, action2ID, AccessType.Allow);


            authorized = securityPermissions.IsGranted(role1ID, document1ID, action1ID, BuiltInStates.Any);
            Assert.IsTrue(authorized, "role1 should have full control for document1");


            bool authorized1 = securityPermissions.IsGranted(role1ID, document1ID, action2ID, BuiltInStates.Any);
            Assert.IsTrue(authorized1, "role1 should have full control for document1");


            Assert.AreEqual(2, securityPermissions.GetPermissions(role1ID, document1ID).Length);

            securityPermissions.DenyPermission(role1ID, document1ID, action1ID);
            bool authorized3 = securityPermissions.IsGranted(role1ID, document1ID, action1ID, BuiltInStates.Any);
            Assert.IsFalse(authorized3);

            bool authorized4 = securityPermissions.IsGranted(role1ID, document1ID, action2ID, BuiltInStates.Any);
            Assert.IsTrue(authorized4);


            securitySpace.Clear();
        }


        [Test, Description("Is granted on role for document")]
        public void IsGrantedOnRoleForDocument()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            ISecurityPermissions securityPermissions = TestsHelper.GetSecurityPermissions();
            bool authorized = true;
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsFalse(authorized);
            Assert.AreEqual(0, securityPermissions.GetPermissions(role1ID, document1ID).Length);
            //grant full control.
            securityPermissions.GrantPermission(role1ID, document1ID);
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsTrue(authorized, "role1 should have full control for document1");
            Assert.AreEqual(1, securityPermissions.GetPermissions(role1ID, document1ID).Length);
            securitySpace.Clear();
        }


        [Test, Description("Is revoked on for role for document after grant")]
        public void IsRevokedOnRoleForDocument()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            ISecurityPermissions securityPermissions = TestsHelper.GetSecurityPermissions();
            bool authorized = true;
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsFalse(authorized);
            Assert.AreEqual(0, securityPermissions.GetPermissions(role1ID, document1ID).Length);
            //grant full control.
            securityPermissions.GrantPermission(role1ID, document1ID);
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsTrue(authorized, "role1 should have full control for document1");
            Assert.AreEqual(1, securityPermissions.GetPermissions(role1ID, document1ID).Length);
            securityPermissions.RevokePermission(role1ID, document1ID);
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsFalse(authorized);
            securitySpace.Clear();
        }


        [Test, Description("Is revoked on for role for document and actions")]
        public void IsRevokedOnRoleForDocumentAndActions()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            ISecurityPermissions securityPermissions = TestsHelper.GetSecurityPermissions();
            bool authorized = true;
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsFalse(authorized);
            Assert.AreEqual(0, securityPermissions.GetPermissions(role1ID, document1ID).Length);
            //grant full control.
            securityPermissions.GrantPermission(role1ID, document1ID, action1ID);
            securityPermissions.GrantPermission(role1ID, document1ID, action2ID);

            authorized = securityPermissions.IsGranted(role1ID, document1ID, action1ID, BuiltInStates.Any);
            Assert.IsTrue(authorized, "role1 should have full control for document1 on action1ID ");


            authorized = securityPermissions.IsGranted(role1ID, document1ID, action2ID, BuiltInStates.Any);
            Assert.IsTrue(authorized, "role1 should have full control for document1 on action2ID");


            Assert.AreEqual(2, securityPermissions.GetPermissions(role1ID, document1ID).Length);
            //revoke for doc on action1
            securityPermissions.RevokePermission(role1ID, document1ID, action1ID);
            authorized = securityPermissions.IsGranted(role1ID, document1ID, action1ID, BuiltInStates.Any);
            Assert.IsFalse(authorized);

            bool authorized1 = securityPermissions.IsGranted(role1ID, document1ID, action2ID, BuiltInStates.Any);
            Assert.IsTrue(authorized1);
            securitySpace.Clear();
        }


        [Test, Description("Is revoked on for role for document and actions")]
        public void IsRevokedOnRoleForDocumentAndActionsAndState()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            ISecurityPermissions securityPermissions = TestsHelper.GetSecurityPermissions();
            bool authorized = true;
            authorized = securityPermissions.IsGranted(role1ID, document1ID);
            Assert.IsFalse(authorized);
            Assert.AreEqual(0, securityPermissions.GetPermissions(role1ID, document1ID).Length);
            //grant full control.
            securityPermissions.GrantPermission(role1ID, document1ID, action1ID, BuiltInStates.Any);
            securityPermissions.GrantPermission(role1ID, document1ID, action2ID, BuiltInStates.Any);

            authorized = securityPermissions.IsGranted(role1ID, document1ID, action1ID, BuiltInStates.Any);
            Assert.IsTrue(authorized, "role1 should have full control for document1 on action1ID ");


            authorized = securityPermissions.IsGranted(role1ID, document1ID, action2ID, BuiltInStates.Any);
            Assert.IsTrue(authorized, "role1 should have full control for document1 on action2ID");


            Assert.AreEqual(2, securityPermissions.GetPermissions(role1ID, document1ID).Length);
            //revoke for doc on action1
            securityPermissions.RevokePermission(role1ID, document1ID, action1ID, BuiltInStates.Any);
            authorized = securityPermissions.IsGranted(role1ID, document1ID, action1ID, BuiltInStates.Any);
            Assert.IsFalse(authorized);

            bool authorized1 = securityPermissions.IsGranted(role1ID, document1ID, action2ID, BuiltInStates.Any);
            Assert.IsTrue(authorized1);
            securitySpace.Clear();
        }


        public void DenyPermissionOnActionWithState()
        {
            bool authorized = true;
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();


            //create type folder
            ISecuritySecuredType folderType = securitySpace.SecuredTypes.CreateType("folder");
            folderType.Actions.CreateAction(TestActions.List);
            folderType.Actions.CreateAction(TestActions.Read);
            folderType.Actions.CreateAction(TestActions.Create);
            folderType.Actions.CreateAction(TestActions.Modify);
            folderType.Actions.CreateAction(TestActions.Delete);
            folderType.States.CreateState(TestStates.New);

            //save the above
            securitySpace.SecuredTypes.UpdateSecuredType(folderType);
            securitySpace.SecuredDocuments.SetDefaultPathType(folderType);
            securitySpace.SecuredDocuments.SetDefaultDocumentType(folderType);
            ISecuritySecuredDocument securedDocument;
            string commonPath = "/ACME/TA/Common";
            securedDocument = securitySpace.SecuredDocuments.CreatePath(commonPath);

            //create role
            securitySpace.Roles.CreateRole(TestRoles.Users);

            //grand role permission on document path
            ISecurityPermissionsProvider securityPermissionProvider = TestsHelper.GetSecurityPermissions();
            Guid userRoleID = securitySpace.Roles.GetRole(TestRoles.Users).GID;
            Guid DocGuid = securitySpace.SecuredDocuments.GetDocument(commonPath).GID;
            Guid ActionGuid = securitySpace.SecuredDocuments.GetDocument(commonPath).GetActionID(TestActions.Create);
            Guid ActionGuid1 = securitySpace.SecuredDocuments.GetDocument(commonPath).GetActionID(TestActions.Delete);
            Guid StateGuid = securitySpace.SecuredDocuments.GetDocument(commonPath).GetStateID(TestStates.New);

            securityPermissionProvider.CreatePermission(userRoleID, DocGuid, ActionGuid, StateGuid, AccessType.Allow);
            securityPermissionProvider.CreatePermission(userRoleID, DocGuid, ActionGuid1, StateGuid, AccessType.Allow);

            AccessType userAccessType;
            userAccessType = securityPermissionProvider.GetAccessType(userRoleID, DocGuid, ActionGuid, StateGuid);
            Assert.AreEqual(AccessType.Allow, userAccessType);

            ISecurityPermission securityPermission =
                securityPermissionProvider.GetPermission(userRoleID, DocGuid, ActionGuid, StateGuid);

            ISecurityPermissions securityPermissions = TestsHelper.GetSecurityPermissions();

            securityPermissions.DenyPermission(userRoleID, DocGuid, ActionGuid, StateGuid);


            userAccessType = securityPermissionProvider.GetAccessType(userRoleID,
                                                                      DocGuid,
                                                                      ActionGuid,
                                                                      StateGuid);

            Assert.AreEqual(AccessType.Deny, userAccessType);

            AccessType userAccessType1;

            userAccessType1 = securityPermissionProvider.GetAccessType(userRoleID,
                                                                       DocGuid,
                                                                       ActionGuid1,
                                                                       StateGuid);

            Assert.AreEqual(AccessType.Allow, userAccessType1);


            securitySpace.Clear();
        }
    }
}